package com.alcloud.springplus.exception;

import com.alcloud.springplus.base.ResponseData;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.lang.Nullable;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;


/**
 * @className: ApplicationExceptionHandler
 * @description: 内部统一异常捕获
 * @author: AllG
 * @createDate: 2018/12/5 9:51
 * @updateRemark: 更新说明
 */
@ControllerAdvice
public class ApplicationExceptionHandler{

    /**
     * @method  handleException
     * @description 统一异常捕获方法
     * @date: 2018/12/5 10:49
     * @author: AllG
     * @param ex
     * @param request
     * @return org.springframework.http.ResponseEntity<java.lang.Object>
     */
    @ExceptionHandler(Exception.class)
    @Nullable
    final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {

        if (ex instanceof HttpRequestMethodNotSupportedException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.METHOD_NOT_ALLOWED.value(),ex.getMessage()), HttpStatus.METHOD_NOT_ALLOWED);
        }
        else if (ex instanceof HttpMediaTypeNotSupportedException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(),ex.getMessage()), HttpStatus.UNSUPPORTED_MEDIA_TYPE);
        }
        else if (ex instanceof HttpMediaTypeNotAcceptableException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.NOT_ACCEPTABLE.value(),ex.getMessage()), HttpStatus.NOT_ACCEPTABLE);
        }
        else if (ex instanceof MissingPathVariableException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.INTERNAL_SERVER_ERROR.value(),ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
        }
        else if (ex instanceof MissingServletRequestParameterException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof ServletRequestBindingException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof ConversionNotSupportedException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.INTERNAL_SERVER_ERROR.value(),ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
        }
        else if (ex instanceof TypeMismatchException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof HttpMessageNotReadableException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof HttpMessageNotWritableException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.INTERNAL_SERVER_ERROR.value(),ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
        }
        else if (ex instanceof MethodArgumentNotValidException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof MissingServletRequestPartException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof BindException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.BAD_REQUEST.value(),ex.getMessage()), HttpStatus.BAD_REQUEST);
        }
        else if (ex instanceof NoHandlerFoundException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.NOT_FOUND.value(),ex.getMessage()), HttpStatus.NOT_FOUND);
        }
        else if (ex instanceof AsyncRequestTimeoutException) {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.SERVICE_UNAVAILABLE.value(),ex.getMessage()), HttpStatus.SERVICE_UNAVAILABLE);
        }
        else if (ex instanceof ApplicationException) {
            return new ResponseEntity<>(new ResponseData<>(((ApplicationException)ex).getCode(),ex.getMessage()), HttpStatus.OK);
        }
        else {
            return new ResponseEntity<>(new ResponseData<>(HttpStatus.INTERNAL_SERVER_ERROR.value(),ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}
